package TwentyOne;

/*
 * 一个宠物商店，里面可以出售各种宠物，要求可以实现宠物的上架，下架处理，也可以根据关键字查询宠物的信息。
 */
interface ILink<E> {         //设置泛型避免安全隐患

    public void add(E e);   //增加数据

    public int size();    //获取数据的个数

    public boolean isEmpty();   //判断是否空集合

    public Object[] toArray();     //将集合元素以数组的形式返回

    public E get(int index);   //根据索引获取数据

    public void set(int index, E data);    //修改索引数据

    public boolean contains(E data); //判断数据是否存在

    public void remove(E e);        //数据删除

    public void clean();    //清空集合
}

class LinkImpl<E> implements ILink<E> {

    private class Node {         //保存节点的数据关系

        private E data;      //保存数据
        private Node next;       //保存下一个引用

        public Node(E data) {          //有数据的情况下才有意义
            this.data = data;
        }
        //第一次调用：this = LinkImpl.root ;
        //第二次调用：this = LinkImpl.root.next ;
        //第三次调用：this = LinkImpl.root.next.next ;

        public void addNode(Node newNode) {      //保存新的Node数据
            if (this.next == null) {   //当前节点的下一个节点为null
                this.next = newNode;      //保存当前节点
            } else {
                this.next.addNode(newNode);
            }
        }
        //第一次调用：this = LinkImpl.root
        //第二次调用：this = LinkImpl.root.next
        //第三次调用：this = LinkImpl.root.next.next

        public void toArrayNode() {
            LinkImpl.this.returnData[LinkImpl.this.foot++] = this.data;
            if (this.next != null) {     //还有下一个数据
                this.next.toArrayNode();
            }
        }

        public E getNode(int index) {
            if (LinkImpl.this.foot++ == index) {       //索引相同
                return this.data;    //返回当前数据
            } else {
                return this.next.getNode(index);
            }
        }

        public void setNode(int index, E data) {
            if (LinkImpl.this.foot++ == index) {       //索引相同
                this.data = data;    //修改数据
            } else {
                this.next.setNode(index, data);
            }
        }

        public boolean containsNode(E data) {
            if (data.equals(this.data)) {    //对象比较
                return true;
            } else {
                if (this.next == null) {         //没有后续节点
                    return false;   //找不到
                } else {
                    return this.next.containsNode(data);   //向后继续判断 
                }
            }
        }

        public void removeNode(Node<E> previous, E data) {
            if (this.data.equals(data)) {
                previous.next = this.next;
            } else {
                if (this.next != null) {
                    this.next.removeNode(this, data);
                }
            }
        }

        public void removeNode(Node previous, E data) {
            if (this.data.equals(data)) {
                previous.next = this.next;    //空出当前节点
            } else {
                if (this.next != null) {       //有后续节点
                    this.next.removeNode(this, data);    //向后继续删除
                }
            }
        }
    }
    //------------以下为Link类中定义的成员-----------------
    private Node root;       //保存根元素
    private int count;     //保存数据的个数
    private int foot;     //描述的是操作数组的脚标
    private Object[] returnData;   //返回的数据保存
    //------------以下为Link类中定义的方法-----------------

    public void add(E e) {
        if (e == null) {
            return;
        }
        //数据本身是不具有关联特性的，只有Node类有，要想关联处理就必须将数据包装在Node类中
        Node newNode = new Node(e);    //创建一个新的节点
        if (this.root == null) {            //现在没有根节点
            this.root = newNode;       //第一个节点作为根节点
        } else {                          //根节点存在
            this.root.addNode(newNode);       //将新节点保存在合适的位置
        }
        this.count++;
    }

    public int size() {
        return this.count;
    }

    public boolean isEmpty() {
        //return this.root == null ;
        return this.count == 0;
    }

    public Object[] toArray() {
        if (this.isEmpty()) {           //空集合
            return null;      //现在没有数据
        }
        this.foot = 0 ;  //脚标清零
         this.returnData = new Object[this.count];   //根据已有的长度开辟数组
        this.root.toArrayNode(); //利用Node类进行递归数据获取
        return this.returnData;
    }

    public E get(int index) {
        if (index >= this.count) {    //索引应该在指定的范围之内
            return null;
        }    //索引数据的获取应该由Node类完成
        this.foot = 0;   //重置索引的下标
        return this.root.getNode(index);
    }

    public void set(int index, E data) {
        if (index >= this.count) {    //索引应该在指定的范围之内
            return;     //方法结束
        }    //索引数据的获取应该由Node类完成
        this.foot = 0;   //重置索引的下标
        this.root.setNode(index, data);  //修改数据
    }

    public boolean contains(E data) {
        if (data == null) {
            return false;     //没有数据
        }
        return this.root.containsNode(data);    //交给Node类判断
    }

    public void remove(E data) {
        if (this.contains(data)) {     //判断数据是否存在
            if (this.root.data.equals(data)) {       //根节点为要删除节点
                this.root = this.root.next;    //根的下一个节点  
            } else {         //交由Node类进行删除
                this.root.next.removeNode(this.root, data);
            }
            this.count-- 

    
        

    
    ；
         }
  }
  public void clean() {
        this.root = null;  //后续的所有节点都没了
        this.count = 0;   //个数清零
    }
}

interface Pet {            //定义宠物标准

    public String getName();       //获得名字

    public String getColor();       //获得颜色
}

class Petshop {                 //宠物商店

    private ILink<Pet> allPets = new LinkImpl<Pet>();  //保存多个宠物

    public void add(Pet pet) {      //追加宠物，商品上架
        this.allPets.add(pet);      //集合中保存对象
    }

    public void delete(Pet pet) {
        this.allPets.remove(pet);
    }

    public ILink<Pet> search(String keyword) {
        ILink<Pet> searchresult = new LinkImpl<Pet>(); //保存查询结果
        Object result[] = this.allPets.toArray();      //获取全部数据
        if (result != null) {
            for (Object obj : result) {
                Pet pet = (Pet) obj;
                if (pet.getName().contains(keyword)
                        || pet.getColor().contains(keyword)) {
                    searchresult.add(pet); //保存查询结果
                }
            }
        }
        return searchresult;
    }
}

class Cat implements Pet { //实现宠物标准

    private String name;
    private String color;

    public Cat(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public String getName() {
        return this.name;
    }

    public String getColor() {
        return this.color;
    }

    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Cat)) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        Cat cat = (Cat) obj;
        return this.name.equals(cat.name) && this.color.equals(cat.color);
    }

    public String toString() {
        return "【宠物猫】名字：" + this.name + "、颜色：" + this.color;
    }
}

class Dog implements Pet {

    private String name;
    private String color;

    public Dog(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public String getName() {
        return this.name;
    }

    public String getColor() {
        return this.color;
    }

    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Dog)) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        Dog dog = (Dog) obj;
        return this.name.equals(dog.name) && this.color.equals(dog.color);
    }

    public String toString() {
        return "【宠物狗】名字：" + this.name + "、颜色：" + this.color;
    }
}

public class a20_PetShop {

    public static void main(String[] args) {
        Petshop shop = new Petshop();  //开店
        shop.add(new Dog("黄斑狗", "绿色"));
        shop.add(new Cat("小强猫", "深绿色"));
        shop.add(new Dog("黄猫", "深色"));
        shop.add(new Dog("黄狗", "黄色"));
        shop.add(new Dog("斑点狗", "灰色"));
        Object result[] = shop.search("黄").toArray();
        for (Object obj : result) {
            System.out.println(obj);
        }
    }
}
